package netty.person;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import netty.idle.MyIdleHandler;
import netty.websocket.MyServerHandler;

import java.util.concurrent.TimeUnit;


public class MyService {

    public static void main(String[] args) throws InterruptedException {
        // 生成对象
        // protoc --java_out=src/main/java src/protobuf/Person.proto
        EventLoopGroup bossExecutors = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {

            ServerBootstrap serverBootstrap = new ServerBootstrap();
            //在Websocket中一共有六种frame：
            //BinaryWebsocketFrame：发送二进制信息
            //CloseWebsocketFrame：关闭
            //PingWebSocketFrame：心跳检测
            //PongWebSocketFrame:接收心跳检测
            //TextWebSocketFrame:发送文本信息
            serverBootstrap.group(bossExecutors, workerGroup).channel(NioServerSocketChannel.class).
                    handler(new LoggingHandler(LogLevel.INFO)).
                    childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ChannelPipeline pipeline = ch.pipeline();
                            //解码时，解决粘包/半包的问题
                            pipeline.addLast(new ProtobufVarint32FrameDecoder());
                            //对接收到的信息，使用protobuf进行解码
                            pipeline.addLast(new ProtobufDecoder(MyDataInfo.Person.getDefaultInstance()));
                            //编码时，解决粘包/半包的问题
                            pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
                            //对于要发送的信息，使用protobuf进行编码
                            pipeline.addLast(new ProtobufEncoder());
                            pipeline.addLast(new SimpleChannelInboundHandler<MyDataInfo.Person>() {
                                @Override
                                protected void channelRead0(ChannelHandlerContext ctx, MyDataInfo.Person msg) throws Exception {
                                    System.out.println(msg.getName());
                                    System.out.println(msg.getAge());
                                    System.out.println(msg.getAddress());
                                    MyDataInfo.Person person = MyDataInfo.Person.newBuilder().
                                            setName("李四").setAge(23).setAddress("北京").build();
                                    //给服务端发送数据
                                    ctx.channel().writeAndFlush(person);
                                }
                            });


                        }
                    });

            ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();

            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            bossExecutors.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
